#! /usr/bin/perl

#also enable strict mode
use strict;

#use the HMTLSubs package and ValidationSubs package
use HTMLSubs;
use ValidationSubs;
use DBQueries;
use CGI;

#use the MD5 package
use Digest::MD5 qw(md5 md5_hex md5_base64);

#start by obtaining the input so that the username can be determined
my $input = obtain_input();

#ensure that input is not blank which would mean that the site is illegally accessed
if(length($input) == 0){
	
	#if so, redirect to login
	print CGI -> redirect("login.pl.cgi");
}

#declare global variable to hold username
my $username;

#call method to split the full string into a hash of individual variables
#this subroutine returns a reference to the submitted info hash
my $ref_submitted_passwords = HTMLSubs->decode_input($input);

#dereference the hash
my %submitted_passwords = %$ref_submitted_passwords;

#now decode the input so that the script can determine if any new information was passed or if the script simply obtained a username
if(scalar(keys %submitted_passwords) == 1){
	
	#in this case the user has not updated any infomration yet and the update page will be displayed for the first time
	#therefore isolate username and call database
	$username = $submitted_passwords{'username'};
	
	#now display the submission form with no error message
	display_change_password();
}

#otherwise we know that a password change was submitted so determine if valid
else{
	
	#now call subroutine to process input
	#pass this sub the reference to submitted info
	#this subroutine will take control of the flow of the script and determine what actions to further take
	process_update($ref_submitted_passwords);
}

#subroutine to both determine the validity of the users input and to process the submission
#this subroutine will call a subroutine to determine if each of the data fields was entered correctly
sub process_update{
	
	#obtain user information from parameter
	my $ref_submitted_passwords = $_[0];
	
	#dereference hash to local variable
	my %submitted_passwords = %$ref_submitted_passwords;
	
	#obtain username
	$username = $submitted_passwords{'username'};
	
	#first determine if the two new passwords are valid and identical
	if(ValidationSubs -> validate_passwords($submitted_passwords{'password1'}, $submitted_passwords{'password2'}) == 0){
		
		#if they are not, produce appropriate error message and redisplay submission
		my $error_message = "<h4><font color=\"red\">Your new passwords did not match or were empty! Please try again.</font></h4>";
		
		#now redisplay
		display_change_password($error_message);
	}
	#now make sure that the former password is valid
	else{
		
		#obtain current password from database
		my $current_password = DBQueries::getUserPassword($username);
		
		#md5 the password entered
		my $hashed_current_input = md5_hex($submitted_passwords{'initialPW'});
		
		#now compare
		#if it matches show success and store
		if($current_password eq $hashed_current_input){
			
			#store hash of entered password
			#md5 the password so that it is securely stored
			my $hashed_password = md5_hex($submitted_passwords{'password1'});

			#now update the database
			DBQueries::updateUserPassword($username, $hashed_password);
			
			#call method to show the success page
			show_success($username);
		}
		
		#otherwise the current password was not enterd correctly so produce the correct error message and redisplay the form
		else{
			
			my $error_message = "<h4><font color=\"red\">You did not enter the correct current password! Please try again.</font></h4>";
			
			#now redisplay
			display_change_password($error_message);
		}
	}
}

#subroutine that is called whenever the user succesfully changes the password
#this subroutine will display a success message to the user before redirecting to the main window
#this sub is passed one parameter, the username
sub show_success{
	
	#obtain parameter
	my $username = $_[0];
	
	#call method to display html beginnign
	HTMLSubs->generate_html_beginning("Successfully Changed Password!");
	
	#obtain general user info from DB
	#declare scalars to hold most important information
	my $groups_owned = scalar(DBQueries::getUserCreatedGroups($username));
	my $groups_member = scalar(DBQueries::getUserGroups($username));
	my $files_owned = scalar(DBQueries::getUserFileNames($username));
	my $files_seeable = scalar(DBQueries::getAllUserFileNames($username));
	my($first_name, $last_name) = DBQueries::getUserInfo($username);
	
	#call sub to print header
	HTMLSubs -> generate_display_head("Document Management System", "Successfully Changed Password", $username);

	print <<END_HTML;
	
	<!--now display the message to the user-->
	<h4>Please return to your profile for further action.</h4>
	<br>
	
END_HTML

	#create hash for button
	my %username_hash;
	$username_hash{'username'} = $username;
	
	#call subroutine to display button that returns the user to the profile
	HTMLSubs -> generate_html_button("profile.pl.cgi", "Go To profile", \%username_hash);

	#now call method to produce closing html tags
	HTMLSubs->generate_html_end();
}

#subroutine to display the update page
#this subroutine accepts an error message as a parameter to be displayed above the submission form
sub display_change_password{
	
	#obtain potential messages
	my $error_text = $_[0] || "";
	
	#call routine to display beginning of html
	HTMLSubs -> generate_html_beginning("Change Password");
	
	#call the subroutine to create the html code for the actual form and pass it the correct entries reference
	generate_password_change_html($ENV{'SCRIPT_NAME'}, $error_text);
	
	#call the subroutine to end the html code
	HTMLSubs -> generate_html_end();
}

#subroutine to create the html password form
#this sub is passed the name of the target for the form and an error text
sub generate_password_change_html{
	
	#obtain target
	my $form_target = $_[0];
	my $error_text = $_[1];
	
	#create a hash containing only the username key/value pair to be passed to the button creation subroutine
	my %username_hash;
	$username_hash{'username'} = $username;
	
	#obtain general user info from DB
	#declare scalars to hold most important information
	my $groups_owned = scalar(DBQueries::getUserCreatedGroups($username));
	my $groups_member = scalar(DBQueries::getUserGroups($username));
	my $files_owned = scalar(DBQueries::getUserFileNames($username));
	my $files_seeable = scalar(DBQueries::getAllUserFileNames($username));
	my($first_name, $last_name) = DBQueries::getUserInfo($username);
	
	#call sub to print header
	HTMLSubs -> generate_display_head("Document Management System", "Successfully Changed Password", $username);

	print <<END_HTML;
	
	<!--now move to the main content of the site-->
	<div class="content">
END_HTML

	#print any potential error messages passed to the subroutine and ensure that not too many <br> tags are printed
	#by determining if the length of the text is 0 or not
	if(length($error_text) != 0){
		print "<p>$error_text</p>";
	}
	print <<END_HTML;
	<!-- place form in table for appearance formatting-->
	<table>
		<form action="$form_target" method=POST>
		<!--old password-->
		<tr>
			<td><p>Current Password:</p></td>
			<td><input type="password" name="initialPW"></td>
		</tr>
		<!--new password-->
		<tr>
			<td><p>New Password:</p></td>
			<td><input type="password" name="password1"></td>
		</tr>
		<!--repeat new password-->
		<tr>
			<td><p>Repeat New Password:</p></td>
			<td><input type="password" name="password2"></td>
		</tr>
		
		<!-- now create a hidden field that resubmits the usernmae so that the script knows what user is being passed back-->
		<input type="hidden" name="username" value="$username">
		
		<tr>
			<td><input type="submit" value="Submit"></form>
END_HTML
			#call subroutine to crate a cancel button
			#this subroutine takes the name of a script and the value of the button 
			HTMLSubs -> generate_html_button("profile.pl.cgi", "Cancel", \%username_hash);
			
			#print remainder of html
			print <<END_HTML;
			</td>
		</tr>
	</table>
END_HTML
	
}	

#subroutine to obtain and determine what information is passed to the script
#to make this more universal, both GET and POST methods are accepted 
#this reads input for both GET and POST
sub obtain_input{

	#declare scalar to hold passed information
	my $input;

	#now retrieve the input through either get or post
	#change the case of request method
	$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;

	#if post use STDIN
	if ($ENV{'REQUEST_METHOD'} eq "POST"){
		read(STDIN, $input, $ENV{'CONTENT_LENGTH'});

		#exchange plus signs to spaces
		$input =~ s/\+/ /;

		#deal with special characters using the substitution sample provided
		$input =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
	}
	#otherwise the env hash
	else{
		$input = $ENV{'QUERY_STRING'};
		
		#exchange plus signs to spaces
		$input =~ s/\+/ /;
		
		#deal with special characters using the substitution sample provided
		$input =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
	}
	
	#now return the correct input
	return $input;	
}

	
